package com.wbsxch.blog.security;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wbsxch.blog.entity.Permission;
import com.wbsxch.blog.entity.User;
import com.wbsxch.blog.security.exception.UserNotActivatedException;
import com.wbsxch.blog.service.security.PermissionService;
import com.wbsxch.blog.service.security.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Authenticate a user from the database.
 */
@Component("userDetailsService")
public class UserModelDetailsService implements UserDetailsService {

   private final Logger log = LoggerFactory.getLogger(UserModelDetailsService.class);

   private final UserService userService;
   private final PermissionService permissionService;

   public UserModelDetailsService(UserService userService, PermissionService permissionService) {
      this.userService = userService;
      this.permissionService = permissionService;
   }

   @Override
   @Transactional
   public UserDetails loadUserByUsername(final String login) {
      log.debug("Authenticating user '{}'", login);
      User user = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, login));
      if(user == null) throw new UsernameNotFoundException("User " + login + " was not found in the database");
      return createSpringSecurityUser(login,user);

   }

   private org.springframework.security.core.userdetails.User createSpringSecurityUser(String lowercaseLogin, User user) {
      if (user.getState() != 1) {
         throw new UserNotActivatedException("User " + lowercaseLogin + " was not activated");
      }
      List<Permission> permissions = permissionService.selectPermissionListByUserId(user.getId());
      List<GrantedAuthority> grantedAuthorities = permissions.stream()
         .map(authority -> new SimpleGrantedAuthority(authority.getPermissionCode()))
         .collect(Collectors.toList());
      return new org.springframework.security.core.userdetails.User(user.getUsername(),
         user.getPassword(),
         grantedAuthorities);
   }
}
